#include<sys/shm.h>
#include<sys/ipc.h>
#include <sys/types.h>
#include <cstring>
#include <iostream>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
#define PATHNAME "."
#define PROJID 0x6666
size_t SIZE=4096;
#define SERVER 1
#define CLIENT 0
key_t getKey()
{
    key_t key=ftok(PATHNAME,PROJID);
    if(key==-1)
    {
        cerr<<"error :"<<errno<<strerror(errno)<<endl;
        exit(1);
    }
    return key;
}

int createShm(int shmflag)
{
    key_t key=getKey();
    int shmid= shmget(key,SIZE,shmflag);
    if(shmid==-1)
    {
        cerr<<"error :"<<errno<<strerror(errno)<<endl;
    }
    return shmid;
}
int serverShm()//服务器创建共享内存
{
    return createShm(IPC_CREAT|IPC_EXCL| 0666);
}
int clientShm()//客户端获取共享内存
{
    return createShm(IPC_CREAT);
}
char* attachShm(int shmid)//连接共享内存
{
    char* start=(char*)shmat(shmid,nullptr,0);
    return start;
}
void undoShm(const char* start)//去关连
{
    int ret=shmdt(start);
    if(ret==-1)
    {
        cerr<<"error :"<<errno<<strerror(errno)<<endl;
    }
}
void delShm(int shmid)
{
    int n=shmctl(shmid,IPC_RMID,nullptr);
    assert(n!=-1);
    (void)n;
}
class Init
{
public:
    Init(int type)
    :_type(type)
    {
        _key=getKey();
        if(_type==SERVER)
        {
            _shmid=serverShm();
        }
        else
        {
            _shmid=clientShm();
        }
        _start=attachShm(_shmid);
    }
    int _getShmid()
    {
        return _shmid;
    }
    int _getKey()
    {
        return _key;
    }
    char* getShmaddr()
    {
        return _start;
    }
    ~Init()
    {
        undoShm(_start);
        if(_type == SERVER) delShm(_shmid);
    }

private:
    char* _start;
    int _shmid;
    int _key;
    int _type;

};
//key_t ftok(const char *pathname, int proj_id)